/**
 * MQ2传感器驱动 - 实现文件
 */
#include "mq2_sensor.h"
#include "driver/adc.h"
#include "driver/gpio.h"
#include "esp_adc_cal.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"

// 默认配置实现
const mq2_config_t MQ2_DEFAULT_CONFIG = {
        .adc_channel = ADC1_CHANNEL_6,     // GPIO34
        .adc_vref = 1100,                  // 参考电压1.1V
        .do_pin = -1,                      // 默认不使用DO引脚
        .threshold_normal = 1000,          // 正常范围上限
        .threshold_warning = 1800,         // 警告范围上限
        .threshold_danger = 2500,          // 危险范围上限
        .gas_multipliers = {
                1.0f,  // 正常空气
                1.5f,  // 烟雾
                1.8f,  // 液化石油气
                1.6f,  // 甲烷
                2.0f   // 氢气
        },
        .baseline = 0,
        .is_initialized = false
};

// ADC校准特性
static esp_adc_cal_characteristics_t adc_chars;

bool mq2_init(mq2_config_t *config) {
    if (!config || config->is_initialized) {
        return false;
    }

    // 配置ADC
    adc1_config_width(ADC_WIDTH_BIT_12);
    adc1_config_channel_atten(config->adc_channel, ADC_ATTEN_DB_11);

    // 配置ADC校准
    esp_adc_cal_characterize(
            ADC_UNIT_1,
            ADC_ATTEN_DB_11,
            ADC_WIDTH_BIT_12,
            config->adc_vref,
            &adc_chars
    );

    // 如果配置了DO引脚，设置为输入模式
    if (config->do_pin >= 0) {
        gpio_reset_pin(config->do_pin);
        gpio_set_direction(config->do_pin, GPIO_MODE_INPUT);
    }

    // 初始化完成
    config->is_initialized = true;
    return true;
}

void mq2_preheat(mq2_config_t *config, uint32_t seconds) {
    if (!config || !config->is_initialized) {
        return;
    }

    printf("MQ2传感器预热中，请等待%d秒...\n", seconds);
    vTaskDelay(pdMS_TO_TICKS(seconds * 1000));
}

uint32_t mq2_measure_baseline(mq2_config_t *config, uint32_t samples) {
    if (!config || !config->is_initialized || samples == 0) {
        return 0;
    }

    uint32_t sum = 0;
    printf("正在测量环境基线值...\n");

    for (uint32_t i = 0; i < samples; i++) {
        uint32_t reading = adc1_get_raw(config->adc_channel);
        uint32_t voltage = esp_adc_cal_raw_to_voltage(reading, &adc_chars);
        sum += voltage;
        vTaskDelay(pdMS_TO_TICKS(1000));
    }

    config->baseline = sum / samples;
    printf("环境基线值: %u mV\n", config->baseline);
    return config->baseline;
}

bool mq2_read_data(mq2_config_t *config, mq2_data_t *data) {
    if (!config || !config->is_initialized || !data) {
        return false;
    }

    // 读取ADC值并转换为电压
    uint32_t adc_reading = 0;
    const uint32_t samples = 64;  // 采样次数

    for (uint32_t i = 0; i < samples; i++) {
        adc_reading += adc1_get_raw(config->adc_channel);
    }
    adc_reading /= samples;

    data->voltage = esp_adc_cal_raw_to_voltage(adc_reading, &adc_chars);

    // 计算浓度百分比
    if (data->voltage > config->baseline) {
        data->concentration = ((float)(data->voltage - config->baseline) /
                               (config->threshold_danger - config->baseline)) * 100.0f;
    } else {
        data->concentration = 0.0f;
    }

    // 限制在0-100%范围内
    if (data->concentration > 100.0f) {
        data->concentration = 100.0f;
    }

    // 确定浓度等级
    if (data->voltage < config->threshold_normal) {
        data->level = LEVEL_NORMAL;
    } else if (data->voltage < config->threshold_warning) {
        data->level = LEVEL_WARNING;
    } else if (data->voltage < config->threshold_danger) {
        data->level = LEVEL_DANGER;
    } else {
        data->level = LEVEL_CRITICAL;
    }

    // 识别可能的气体类型
    data->gas_type = GAS_NORMAL;

    if (data->voltage > config->threshold_danger) {
        if (data->voltage > config->threshold_danger * config->gas_multipliers[GAS_HYDROGEN]) {
            data->gas_type = GAS_HYDROGEN;
        } else if (data->voltage > config->threshold_danger * config->gas_multipliers[GAS_LPG]) {
            data->gas_type = GAS_LPG;
        } else if (data->voltage > config->threshold_danger * config->gas_multipliers[GAS_METHANE]) {
            data->gas_type = GAS_METHANE;
        } else if (data->voltage > config->threshold_danger * config->gas_multipliers[GAS_SMOKE]) {
            data->gas_type = GAS_SMOKE;
        } else {
            data->gas_type = GAS_UNKNOWN;
        }
    }

    // 读取DO引脚状态（如果配置了）
    if (config->do_pin >= 0) {
        data->do_state = (gpio_get_level(config->do_pin) == 0);  // DO引脚低电平表示检测到气体
    } else {
        data->do_state = false;
    }

    return true;
}

const char* mq2_get_gas_type_string(mq2_gas_type_t gas_type) {
    switch (gas_type) {
        case GAS_NORMAL: return "正常空气";
        case GAS_SMOKE: return "烟雾";
        case GAS_LPG: return "液化石油气";
        case GAS_METHANE: return "甲烷";
        case GAS_HYDROGEN: return "氢气";
        case GAS_UNKNOWN: return "未知气体";
        default: return "错误";
    }
}

const char* mq2_get_level_string(mq2_level_t level) {
    switch (level) {
        case LEVEL_NORMAL: return "正常";
        case LEVEL_WARNING: return "警告";
        case LEVEL_DANGER: return "危险";
        case LEVEL_CRITICAL: return "严重危险";
        default: return "错误";
    }
}
